home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Copyright 1993, 1994, Cornell University
-
- Cornell hereby grants permission to use, copy, modify, and distribute this program for any purpose
- and without fee, provided that these copyright and permission notices appear on all copies and
- supporting documentation, the name of Cornell not be used in advertising or publicity pertaining
- to distribution of the program without specific prior permission, notice be given in supporting
- documentation that copying and distribution is by permission of Cornell. CORNELL MAKES NO
- REPRESENTATIONS OR WARRANTEES, EXPRESS OR IMPLIED. By way of example, but not limitation,
- CORNELL MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
- PURPOSE OR THAT THE USE OF THIS SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS,
- TRADEMARKS, OR OTHER RIGHTS. Cornell shall not be held liable for any liability with respect to
- any claim by the user or any other party arising from use of the program.
-
- This material is partially based on work sponsored by the National Science Foundation under Cooperative
- Agreement No. NCR-9318337. The government has certain rights in this material.
-
- */
-
- #include <stdio.h>
- #include <signal.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
-
- #ifndef LINUX
- #include <sys/socketvar.h>
- #endif
-
- #include <sys/time.h>
- #include <netinet/in.h>
-
- #include "reflect.h"
- #include "refmon.h"
- #include "rtp.h"
-
- #include "globals.h"
-
-
- void mbone_pkt(msg,msglen,csock,type)
- unsigned char *msg;
- int msglen;
- struct sockaddr_in csock;
- short type;
- {
-
- struct CtrlMsgHdr *cmhptr;
- struct IDMsgHdr *idh;
- vat_client *mcltptr,*mtmp;
- client *ctmp;
- vat_hdr_t *vat_hdr;
- VideoPacketHeader *vtmp;
- unsigned char nsid;
- unsigned long *ulptr,ul;
- unsigned short *usptr;
- SiteId *siptr;
- char *tmp,buf[50];
- int i;
- unsigned char *cptr,*cptr1;
- struct sockaddr_in tmp1;
- struct in_addr in;
- client *nvcptr;
-
- switch (type)
- {
-
- case VAT_CNTL:
- case MAVEN_CNTL:
-
- /* check what kind of vat/maven cntrl message it is, act accordingly */
-
- cmhptr = (struct CtrlMsgHdr *) msg;
-
- if ((vat_confid != 0) && (ntohs(cmhptr->confid) != vat_confid))
- return;
-
- switch (cmhptr->type)
- {
- case CTRL_TYPE_ID:
- #ifdef DEBUG
- if (debug)
- printf("type = CTRL_TYPE_ID\n");
- #endif
-
- if ((mcltptr = find_vat_client(csock.sin_addr.s_addr)) == NULL)
- {
- if ((mcltptr = new_vat_client(csock.sin_addr.s_addr)) == NULL)
- return;
-
- strncpy(mcltptr->mvn_name,cmhptr->idmsg,MAX_MAVEN_NAME_LEN);
-
- mcltptr->mvn_flags = VAT_CLIENT;
-
- dolog("New Maven client %s at %s\n", mcltptr->mvn_name,inet_ntoa(csock.sin_addr));
-
- if (type == VAT_CNTL)
- mcltptr->mvn_recv_type = MCAST;
- else
- mcltptr->mvn_recv_type = UCAST;
-
- mcltptr->mvn_idlist = NULL;
-
- send_vat_idlist();
- }
- else
- if (strncmp(mcltptr->mvn_name,cmhptr->idmsg,MAX_MAVEN_NAME_LEN))
- {
- strncpy(mcltptr->mvn_name,cmhptr->idmsg,MAX_MAVEN_NAME_LEN);
- #ifdef DEBUG
- if (debug)
- printf("Maven client at %s changing name to %s\n", inet_ntoa(csock.sin_addr),mcltptr->mvn_name);
- #endif
- }
-
- mcltptr->mvn_rtimer = 0;
- break;
-
- case CTRL_TYPE_DONE:
- #ifdef DEBUG
- if (debug)
- printf("type = CTRL_TYPE_DONE\n");
- #endif
- if ((mcltptr = find_vat_client(csock.sin_addr.s_addr)) == NULL)
- return;
-
- delete_vat_client(mcltptr);
- return;
-
- case CTRL_TYPE_IDLIST:
- #ifdef DEBUG
- if (debug)
- printf("type = CTRL_TYPE_IDLIST\n");
- #endif
- if ((mcltptr = find_vat_client(csock.sin_addr.s_addr)) == NULL)
- {
- if ((mcltptr = new_vat_client(csock.sin_addr.s_addr)) == NULL)
- return;
-
- /*
- this is the first idlist message from this mixer, so set the speaker
- list to NULL because we haven't gotten any actual audio data yet
- */
-
- dolog("New Maven client (VAT MIXER) at %s\n", inet_ntoa(csock.sin_addr));
- mcltptr->mvn_flags = VAT_MIXER;
-
- if (type == VAT_CNTL)
- mcltptr->mvn_recv_type = MCAST;
- else
- mcltptr->mvn_recv_type = UCAST;
-
- if ((mcltptr->mvn_idlist = (struct IDMsgHdr *) malloc(msglen)) == NULL)
- {
- dolog("OUT OF MEMORY...ABORTING\n");
- exit(-1);
- }
-
- bcopy((char *) msg, (char *) mcltptr->mvn_idlist, msglen);
- mcltptr->mvn_idlist_len = msglen;
- send_vat_idlist();
- }
- else
- {
- /*
- make this message the new idlist for this maven client, update the
- client's vms_head list, and then free up the old space. This
- must be done every time because even if the idlist contains the
- same information (which may or may not be true), it may contain
- it in a different order. Better safe than sorry.
- */
-
- mcltptr->mvn_idlist_len = msglen;
-
- /*
- idh is a temp pointer. It points to where the new idlist is
- put into memory. Eventually the space pointed to by the old
- mcltptr->idlist is freed and the pointer updated to point to
- the new list
- */
-
- if ((idh = (struct IDMsgHdr *) malloc(msglen)) == NULL)
- {
- dolog("OUT OF MEMORY...ABORTING\n");
- exit(-1);
- }
-
- bcopy((char *) msg, (char *) idh, msglen);
- free((void *) mcltptr->mvn_idlist);
- mcltptr->mvn_idlist = idh;
- }
- return;
-
- default:
- dolog("unrecognized vat ctrl type %d \n",cmhptr->type);
- }
-
- mcltptr->mvn_rtimer = 0;
- return;
-
- case VAT:
- case MAVEN:
-
- if ((mcltptr = find_vat_client(csock.sin_addr.s_addr)) == NULL)
- break;
-
- mcltptr->mvn_rtimer = 0;
-
- /*
- if this vat/maven packet doesn't have the right confid, then we can
- just drop it. Make sure to reset msg first!
- */
-
- vat_hdr = (vat_hdr_t *) msg;
-
- if (ntohs(vat_hdr->confid) != vat_confid)
- {
- dolog("Wrong vat conf_id. Dropping packet.\n");
- break;
- }
-
- if ((vat_hdr->nsid & NSID_MASK) == 0)
- {
- /*
- this code puts a 4-byte speaker id in after the vat header in
- order for the receiver to be able to distinguish it from the
- other streams coming from the reflector
- */
-
- tmp = (char *) msg;
- tmp -= 4;
-
- bcopy((char *)msg, tmp, sizeof(vat_hdr_t));
-
- msg += (sizeof(vat_hdr_t) - 4);
-
- ulptr = (unsigned long *) msg;
- *ulptr = mcltptr->mvn_addr.addr;
-
- msg = (unsigned char *) tmp;
-
- vat_hdr = (vat_hdr_t *) msg;
-
- /*
- set the number of speaker id's to 1
- */
-
- vat_hdr->nsid = (vat_hdr->nsid & ~NSID_MASK) | 1;
-
- /*
- increase the length of the packet by four bytes because we
- inserted one four-byte site_id
- */
-
- msglen += 4;
- }
- else
- {
- /*
- Ok, we've received an audio packet with a non-zero nsid field. So
- we need to check whether this is a speaker (or speakers...note that
- this may be coming from more than one speaker at once if it is a
- true vat_mixer) who is currently on the vms list of this maven client.
- If not, add him to the list and send an initial open continue packet.
- If so, get on with the business of sending the packet out.
- */
-
- nsid = (vat_hdr->nsid & NSID_MASK);
-
- cptr = (unsigned char *) msg + sizeof(vat_hdr_t);
-
- for (i = 0; i < nsid; i++)
- {
- ulptr = (unsigned long *) cptr;
- sprintf(buf,"%d.%d.%d.%d\0",
- (unsigned short)*cptr,(unsigned short)*(cptr+1),(unsigned short)*(cptr+2),(unsigned short)*(cptr+3));
- ul = inet_addr(buf);
-
- if ((siptr = find_site_idlist(mcltptr->mvn_idlist, *ulptr)) != NULL)
- {
- /* indicate that this person is a current speaker */
- if ((mtmp = find_vat_client(ul)) == NULL)
- {
- if ((mtmp = new_vat_client(ul)) == NULL)
- return;
-
- mtmp->mvn_flags = VAT_MIXER_CLIENT;
- mtmp->mvn_pptr = mcltptr;
- strncpy(mtmp->mvn_name,siptr->id_string,MAX_MAVEN_NAME_LEN);
- dolog("New Maven client (VAT MIXER CLIENT) at %s\n", inet_ntoa(csock.sin_addr));
- }
-
- if ((mtmp->mvn_spoke == 0) || ((tick_cnt - mtmp->mvn_spoke) >= VAT_SPEAKER_INTERVAL))
- send_vat_ocp(mtmp);
-
- mtmp->mvn_spoke = tick_cnt;
- mtmp->mvn_rtimer = 0;
- }
- else
- {
- dolog("Audio packet received with unknown speaker id. Dropping packet.\n");
- break;
- }
- cptr += 4;
- }
- }
-
- mcltptr->mvn_rtimer = 0;
- if ((mcltptr->mvn_spoke == 0) || ((tick_cnt - mcltptr->mvn_spoke) >= VAT_SPEAKER_INTERVAL))
- send_vat_ocp(mcltptr);
- mcltptr->mvn_spoke = tick_cnt;
- mcltptr->mvn_seq++;
-
- if (mcltptr->mvn_talker == 0)
- dolog("maven at %s is speaking\n",inet_ntoa(csock.sin_addr));
-
- if (mcltptr->mvn_talker++ > 50)
- mcltptr->mvn_talker = 0;
-
- #ifdef MULTI
- if (((vat_out_mcast_sock) || (vat_inout_mcast_sock)) && (type != VAT))
- {
- tmp1.sin_family = AF_INET;
- tmp1.sin_addr.s_addr = htonl(vat_out_mcast.sin_addr.s_addr);
- tmp1.sin_port = htons(vat_port);
- #ifdef DEBUG
- if (debug)
- printf("reflecting vat unicast pkt onto vat mcast address.\n");
- #endif
- if (vat_inout_mcast_sock)
- {
- if (sendto(vat_out_mcast_sock,msg,msglen,0,&tmp1,sizeof(struct sockaddr_in)) != msglen)
- dolog("mcast sendto error");
- }
- else
- {
- if (sendto(vat_inout_mcast_sock,msg,msglen,0,&tmp1,sizeof(struct sockaddr_in)) != msglen)
- dolog("mcast sendto error");
- }
- }
- #endif
-
- mtmp = mhead;
- while (mtmp != NULL)
- {
- if ((mtmp != mcltptr) || (self_reflect == 1))
- {
- if ((mtmp->mvn_recv_type == UCAST) && ((mtmp->mvn_flags & VAT_MIXER_CLIENT) == 0))
- {
- tmp1.sin_family = AF_INET;
- tmp1.sin_port = htons(mtmp->mvn_addr.port);
- tmp1.sin_addr.s_addr = htonl(mtmp->mvn_addr.addr);
- #ifdef DEBUG
- if (debug)
- printf("reflecting MAVEN pkt to ucast maven %s \n", inet_ntoa(tmp1.sin_addr));
- #endif
- if (sendto(maven_sock,msg,msglen,0,&tmp1,sizeof(struct sockaddr_in)) != msglen)
- dolog("maven_cntl sendto error\n");
- }
- }
- mtmp = mtmp->mvn_nptr;
- }
-
- vtmp = (VideoPacketHeader *) (((unsigned char *) msg) - HEADERLEN);
-
- vtmp->routing.dest.family = htons(kGroup);
- vtmp->routing.dest.port = htons(VID_PORT);
- vtmp->routing.src.family = htons(kGroup);
- vtmp->routing.src.port = htons(VID_PORT);
-
- cptr = (unsigned char *) &vtmp->routing.src.addr;
- cptr1 = (unsigned char *) &csock.sin_addr;
- *cptr++ = *cptr1++;
- *cptr++ = *cptr1++;
- *cptr++ = *cptr1++;
- *cptr++ = *cptr1++;
-
- cptr = (unsigned char *) &vtmp->seqNum;
- cptr1 = (unsigned char *) &mcltptr->mvn_seq;
- *cptr++ = *cptr1++;
- *cptr++ = *cptr1++;
- *cptr++ = *cptr1++;
- *cptr++ = *cptr1++;
-
- vtmp->message = htons(kAudio);
- vtmp->dataType = htons(kAudio);
- vtmp->len = htons(msglen + HEADERLEN);
-
- ctmp = chead;
- while (ctmp != NULL)
- {
- if ((ctmp->clnt_config.flags & REC_AUDIO) && (ctmp->clnt_config.flags & WANT_LURCKERS) &&
- (ctmp->clnt_flags & HOLD_DOWN) == 0)
- #ifdef DEBUG
- if (debug)
- {
- in.s_addr = ctmp->clnt_addr.addr;
- printf("reflecting MAVEN pkt to CUME client at %s\n",inet_ntoa(in));
- }
- #endif
- if (sendto(vid_sock,(char *)vtmp,msglen+HEADERLEN,0,&ctmp->clnt_addr,sizeof(struct sockaddr_in)) != msglen+HEADERLEN)
- dolog("Maven send to error in reflect\n");
- ctmp = ctmp->clnt_nptr;
- }
-
- msg = &buffer[40];
-
- break;
-
- case NV_UCAST:
- case NV_MCAST:
-
- if ((nvcptr = find_client(csock.sin_addr.s_addr)) == NULL)
- {
- dolog("NV client at %s is opening a connection\n", inet_ntoa(csock.sin_addr));
-
- if ((nvcptr = get_client()) == NULL)
- {
- dolog("unable to allocate a new nv client\n");
- return;
- }
-
- if ((nvcptr->clnt_id = get_client_id()) == -1)
- {
- dolog("maximum # of clients exceeded\n");
- return;
- }
-
- /*
- was this new nv client also and old vat client, if so
- keep the OCP sequence # space correct
- */
-
- if ((mtmp = find_vat_client(csock.sin_addr.s_addr)) != NULL)
- nvcptr->clnt_ocp_cnt = mtmp->mvn_ocp_seq;
-
- nvcptr->clnt_addr.family = AF_INET;
- bcopy(&csock.sin_addr,&nvcptr->clnt_addr.addr,4);
-
- if (type == NV_UCAST)
- {
- nvcptr->clnt_flags = NV_UCLIENT;
- nvcptr->clnt_addr.port = nv_ucast_port;
- }
- else
- {
- nvcptr->clnt_flags = NV_MCLIENT;
- nvcptr->clnt_addr.port = nv_mcast_port;
- }
-
- nvcptr->clnt_nptr = chead;
- chead = nvcptr;
-
- nv_client_cnt++;
- }
-
- nvcptr->clnt_bytecnt += msglen;
-
- nvcptr->clnt_rtimer = 0;
-
- distribute_nv(&msg,&msglen,nvcptr);
-
- if ((vtmp = nv_to_cuseeme(nvcptr,(struct rtphdr *) msg,msglen)) == NULL)
- {
- in.s_addr = nvcptr->clnt_addr.addr;
- dolog("Unable to convert NV encoding for %s\n",inet_ntoa(in));
- delete_client(nvcptr);
- return;
- }
-
- distribute(vtmp,nvcptr,FALSE);
-
- return;
- }
- }
-
- /*
- takes a nv packet with an rtp (v1) header and creates (in the same buffer) a
- packet with a VideoPacketHeader to transmit to cusm clients. Note that if
- the nv packet contains an RTP SDESC option (or any option, for that matter,
- but SDESC is all nv sends right now) then it ignores it and just takes
- care of the data. Deals with either cusm or nv encoded video but no others.
- */
-
- VideoPacketHeader *nv_to_cuseeme(nvcltptr,rtp_hdr_ptr,msglen)
- client *nvcltptr;
- struct rtphdr *rtp_hdr_ptr;
- int msglen;
- {
-
- struct rtcpsdeschdr *sdesc_ptr;
- VideoPacketHeader vph;
- char *cptr,*cptr1,fin;
- struct rtpopthdr *optr;
- unsigned short *usptr,cnt;
-
- /* move cptr to after the rtp header */
- cptr = (char *) (rtp_hdr_ptr + 1);
-
- vph.len = msglen - sizeof(struct rtphdr) + HEADERLEN;
-
- /*
- if there are rtp options, move cptr to after the options.
- Remember that the option length is in 4-byte words!
- */
-
- if (rtp_hdr_ptr->rh_opts)
- {
- optr = (struct rtpopthdr *) cptr;
- vph.len = vph.len - optr->roh_optlen*4;
-
- if (optr->roh_type == RTPOPT_SDESC)
- {
- sdesc_ptr = (struct rtcpsdeschdr *) optr;
-
- cptr1 = (char *) (sdesc_ptr + 1);
-
- for (cnt = 0; cnt < 19; cnt++)
- {
- if ((nvcltptr->clnt_config.name[cnt] = *(cptr1+cnt)) == 0)
- break;
-
- if (nvcltptr->clnt_config.name[cnt] == '\n')
- nvcltptr->clnt_config.name[cnt] = ' ';
-
- if (nvcltptr->clnt_config.name[cnt] == '\r')
- nvcltptr->clnt_config.name[cnt] = ' ';
- }
- }
-
- fin = optr->roh_fin;
- cptr += 4*(optr->roh_optlen);
- optr = (struct rtpopthdr *) cptr;
-
- while (!fin)
- {
- fin = optr->roh_fin;
- vph.len = vph.len - optr->roh_optlen*4;
- cptr += 4*(optr->roh_optlen);
- optr = (struct rtpopthdr *) cptr;
- }
- }
-
- if (rtp_hdr_ptr->rh_content == RTPCONT_NV)
- {
- return(NULL);
- }
- else
- if (rtp_hdr_ptr->rh_content == RTPCONT_CELLB)
- {
- return(NULL);
- }
- else
- if (rtp_hdr_ptr->rh_content != RTPCONT_CUSEEME)
- return(NULL);
-
-
- /*
- point usptr to the unsigned short type field, which we will need
- to fill into the video packet header. This two-byte field will
- be kept for later, where the length of video data will be
- stored before going out to cusm clients
- */
-
- usptr = (unsigned short *) cptr;
-
- /*
- move cptr to point to where the video packet header will start
- */
-
- cptr -= HEADERLEN;
-
- /*
- now fill in the video-packet header in with all the information we
- presently possess.
- */
-
- vph.dataType = *usptr;
-
- if (rtp_hdr_ptr->rh_sync)
- vph.message = htons(kFrameEndMessage);
- else
- vph.message = htons(kNoMessage);
-
-
- nvcltptr->clnt_seq = ntohs(rtp_hdr_ptr->rh_seq);
-
- vph.seqNum = htonl(nvcltptr->clnt_seq + nvcltptr->clnt_ocp_cnt);
-
- /*
- dolog("nv_to_cuseeme seq # %D\n",vph.seqNum);
- */
-
- vph.routing.dest.port = htons(VID_PORT);
- vph.routing.dest.family = htons(kGroup);
- vph.routing.src.family = htons(kGroup);
- vph.routing.src.port = htons(nv_mcast_port);
-
- /*
- usptr now points to the unsigned short after the video packet header.
- this field is where nv had put the type...now we want to put in
- the actual length (in bytes) of the compressed squares. This is
- equal to the length of the packet minus the header length, minus two
- bytes for this field itself
- */
-
- *usptr = htons(vph.len - HEADERLEN - 2);
-
- vph.len = htons(vph.len);
-
- vph.routing.src.addr = htonl(nvcltptr->clnt_addr.addr);
-
- cptr1 = (char *) &vph;
-
- bcopy(cptr1,cptr,HEADERLEN);
-
- return((VideoPacketHeader *) cptr);
- }
-
- /*
- returns a pointer to the SiteId structure which contains the given
- unsigned long id. Takes a pointer to a struct IDMsgHdr. Returns
- NULL if that id is not found.
- */
-
- SiteId *find_site_idlist(idlist,id)
- struct IDMsgHdr *idlist;
- unsigned long id;
- {
- char *cptr;
- SiteId *siptr;
- int i,temp;
-
- if (idlist->nsids == 0)
- return(NULL);
-
- cptr = (char *) idlist;
- cptr += sizeof(struct IDMsgHdr);
-
- siptr = (SiteId *) cptr;
-
- for (i = 0; i < idlist->nsids; i++)
- {
- if (siptr->site_id == id)
- return(siptr);
-
- temp = strlen(siptr->id_string) + 1;
-
- cptr = &(siptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
- siptr = (SiteId *) cptr;
- }
-
- return(NULL);
- }
-
- send_vat_ocp(mtmp)
- vat_client *mtmp;
- {
-
- VideoPacketHeader *vtmp;
- client *ctmp;
-
- vtmp = make_open_continue(mtmp,0,kOpenConnection,NULL);
-
- ctmp = chead;
- while (ctmp != NULL)
- {
- if ((ctmp->clnt_flags & CLIENT) && ((ctmp->clnt_flags & HOLD_DOWN) == 0))
- {
- vtmp->routing.dest.addr = htonl(ctmp->clnt_addr.addr);
- if (sendto(vid_sock,(char *)vtmp,vtmp->len,0,&ctmp->clnt_addr,sizeof(struct sockaddr_in)) != vtmp->len)
- dolog("Maven send to error in reflect\n");
- }
- ctmp = ctmp->clnt_nptr;
- }
- }
-
-
-
- /*
- construct a generic OpenContinuePacket that will represent mptr
- to the various CU-SeeMe clients. If mptr is a vat mixer (and thus
- siptr is non-NULL, use that site_id as the string to send
- in the OCP.
- */
-
- VideoPacketHeader *make_open_continue(mptr,confid,message,siptr)
- vat_client *mptr;
- short confid;
- short message;
- SiteId *siptr;
- {
-
- VideoPacketHeader *vidptr;
- unsigned char buffer[MAXMSG];
- OpenContinueData ocd;
- char *string;
- unsigned char *msg = &buffer[40];
-
-
- if (siptr != NULL)
- {
- string = (char *) siptr;
- string += sizeof(unsigned long);
- }
- else
- string = (char *) &mptr->mvn_name[0];
-
-
- vidptr = (VideoPacketHeader *) msg;
-
- vidptr->conferenceid = htons(confid);
- vidptr->routing.dest.family = htons(kGroup);
-
- vidptr->routing.src.family = htons(kGroup);
- vidptr->routing.src.port = htons(VID_PORT);
-
- vidptr->routing.src.addr = htonl(mptr->mvn_addr.addr);
-
- vidptr->seqNum = htonl(mptr->mvn_ocp_seq);
-
-
- vidptr->message = htons(message);
- vidptr->dataType = htons(kConfigVideoType);
- vidptr->len = htons(HEADERLEN + sizeof(OpenContinueData));
-
- ocd.clientCount = 0;
- ocd.seqNum = htonl(mptr->mvn_ocp_seq++);
-
- /*
- dolog("make_open_continue seq # %D\n",vidptr->seqNum);
- */
-
- msg = (unsigned char *) ocd.name;
- if (strlen(string) > 19)
- *msg++ = 19;
- else
- *msg++ = strlen(string);
-
- strncpy((char *) msg,string,19);
-
- ocd.sendMode = 0;
- ocd.recvMode = 0;
- ocd.flags = REC_AUDIO | AUDIO_CAPABLE | WANT_LURCKERS;
- ocd.version = NV_CLIENT_VERS;
-
- msg = (unsigned char *) vidptr;
-
- /*
- This gets rid of the padding put between the first two members of ocd
- */
-
- bcopy((char *) &ocd.seqNum,(char *) &ocd.clientCount + sizeof(ocd.clientCount),sizeof(ocd));
-
- msg += HEADERLEN;
-
- bcopy((char *) &ocd, (char *) msg, sizeof(OpenContinueData));
-
- return(vidptr);
- }
-
- void delete_vat_client(mptr)
- vat_client *mptr;
- {
-
- vat_client *mtmp1;
- struct in_addr in;
-
- in.s_addr = mptr->mvn_addr.addr;
-
- dolog("Deleting Maven client at %s\n", inet_ntoa(in));
-
- if (mptr == mhead)
- {
- mhead = mptr->mvn_nptr;
- mtmp1 = mptr;
- mptr = mptr->mvn_nptr;
- free(mtmp1);
- }
- else
- {
- mtmp1 = mhead;
- while (mtmp1->mvn_nptr != mptr)
- mtmp1 = mtmp1->mvn_nptr;
- mtmp1->mvn_nptr = mptr->mvn_nptr;
- mtmp1 = mptr;
- mptr = mptr->mvn_nptr;
- free(mtmp1);
- }
- vat_client_cnt--;
- }
-
- vat_client *new_vat_client(caddr)
- unsigned long caddr;
- {
- vat_client *ctmp;
-
- if ((ctmp = (vat_client *) calloc(1,sizeof(vat_client))) == NULL)
- return(NULL);
-
- ctmp->mvn_addr.addr = caddr;
- ctmp->mvn_addr.port = maven_port;
- ctmp->mvn_addr.family = AF_INET;
-
- ctmp->mvn_nptr = mhead;
- mhead = ctmp;
- vat_client_cnt++;
-
- return(ctmp);
- }
-
- char num_vat_clients(type)
- char type;
- {
- vat_client *mptr;
- char num;
-
- mptr = mhead;
- num = 0;
-
- while (mptr != NULL)
- {
- if (mptr->mvn_recv_type == type)
- num++;
- mptr = mptr->mvn_nptr;
- }
- return(num);
- }
-
-
-
- void vat_id(mptr)
- vat_client *mptr;
- {
- static char buf[MAXMSG];
- struct CtrlMsgHdr *vatIdmsg;
- int msglen;
- struct in_addr in;
- struct sockaddr_in mvnskt;
-
- #ifdef DEBUG
- if (debug)
- {
- in.s_addr = mptr->mvn_addr.addr;
- printf("sending id message to maven at %s\n",inet_ntoa(in));
- }
- #endif
-
- vatIdmsg = (struct CtrlMsgHdr *) buf;
- vatIdmsg->flags = 0;
- vatIdmsg->type = CTRL_TYPE_ID;
- vatIdmsg->confid = 0;
- strcpy(vatIdmsg->idmsg,"CU-Reflector");
- vatIdmsg->idmsg[strlen("CU-Reflector")] = 0;
- msglen = CTRLMSGSIZE + strlen("CU-Reflector") + 1;
-
- mvnskt.sin_family = AF_INET;
- mvnskt.sin_port = mptr->mvn_addr.port + 1;
- mvnskt.sin_addr.s_addr = mptr->mvn_addr.addr;
-
- pkts_out++;
- bytes_out += msglen;
-
- if (sendto(maven_cntl_sock_out,buf,msglen,0,&mvnskt,sizeof(struct sockaddr_in)) != msglen)
- dolog("Maven id sendto error\n");
-
- }
-
-
- /*
- constructs and sends a vat CTRL_TYPE_IDLIST message to all vat and
- maven clients. The function takes care of sending the appropriate
- message to the mcast address and to the ucast vat/mavens that
- are connected... note that these are usually different.
- */
-
- void send_vat_idlist()
- {
- vat_client *mptr,*mptr1;
- char buffer[MAXMSG],*cptr,temp;
- client *cltptr;
- struct IDMsgHdr *idhptr;
- SiteId *sidptr;
- int msglen,i;
- struct sockaddr_in tmp1;
- char num_mcast,num_ucast,count;
-
- num_mcast = num_vat_clients(MCAST);
- num_ucast = num_vat_clients(UCAST);
-
- mptr = mhead;
-
- cptr = buffer + 40 + sizeof(struct IDMsgHdr);
-
- sidptr = (SiteId *) cptr;
- count = 0;
-
- /*
- construct the idlist that represents all ucast mavens to the mcast
- vats. If there are no ucast maven/vats and no cusm clients, send nothing
- */
-
- if (vat_out_mcast.sin_addr.s_addr)
- {
- while (mptr != NULL)
- {
- if (mptr->mvn_recv_type == UCAST)
- {
- if (mptr->mvn_idlist == NULL)
- {
- sidptr->site_id = mptr->mvn_addr.addr;
- strcpy(sidptr->id_string,mptr->mvn_name);
-
- temp = strlen(sidptr->id_string) + 1;
-
- cptr = &(sidptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
- sidptr = (SiteId *) cptr;
- }
- else
- {
- /*
- copy the idlist that this maven client has been sending (see reflect.c)
- into the idlist we are presently building. mptr->idlist points to a
- struct IDMsgHdr, which we don't want, so skip over it.
- */
-
- count += mptr->mvn_idlist->nsids;
-
- cptr = (char *) mptr->mvn_idlist;
- cptr += sizeof(struct IDMsgHdr);
- temp = mptr->mvn_idlist_len - sizeof(struct IDMsgHdr);
-
- bcopy(cptr, (char *) sidptr, temp);
- cptr = (char *) sidptr;
- cptr += temp;
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- sidptr = (SiteId *) cptr;
-
- }
- }
- mptr = mptr->mvn_nptr;
- }
-
- cltptr = chead;
- while (cltptr != NULL)
- {
- if (cltptr->clnt_config.flags & AUDIO_CAPABLE)
- {
- count++;
-
- sidptr->site_id = cltptr->clnt_addr.addr;
- strncpy(sidptr->id_string,cltptr->clnt_config.name,20);
-
- temp = strlen(sidptr->id_string) + 1;
- cptr = &(sidptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- sidptr = (SiteId *) cptr;
- }
-
- cltptr = cltptr->clnt_nptr;
- }
-
- count++;
-
- sidptr->site_id = myaddr.sin_addr.s_addr;
- strncpy(sidptr->id_string,"CU-Reflector ",20);
-
- temp = strlen("CU-Reflector") + 1;
- cptr = &(sidptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- idhptr = (struct IDMsgHdr *) &buffer[40];
- idhptr->flags = 0;
- idhptr->type = CTRL_TYPE_IDLIST;
- idhptr->confid = htons(vat_confid);
- idhptr->nsids = num_ucast + count;
- idhptr->ainfo = 0;
- idhptr->blksize = 0;
-
- msglen = cptr - &buffer[40];
- cptr = &buffer[40];
-
- tmp1.sin_family = AF_INET;
- tmp1.sin_addr.s_addr = htonl(vat_out_mcast.sin_addr.s_addr);
- tmp1.sin_port = htons(vat_port + 1);
-
- #ifdef DEBUG
- if (debug)
- printf("Sending Idlist of UCAST mavens to mcast address \n");
- #endif
- if (sendto(vat_cntl_mcast_sock,cptr,msglen,0,&tmp1,sizeof(struct sockaddr_in)) != msglen)
- dolog("mcast sendto error");
- }
-
- /*
- construct the idlist to send to ucast maven/vat clients. Do not send one if there is
- one or zero clients. (vat_id() takes care of 1, and obviously if there are no
- clients then we don't want to send anything...
- */
-
- if ((mptr = mhead) == NULL)
- return;
-
- if ((mptr->mvn_nptr == NULL) && (chead == NULL))
- vat_id(mptr);
-
- cptr = buffer + 40 + sizeof(struct IDMsgHdr);
-
- sidptr = (SiteId *) cptr;
-
- count = 0;
-
- while (mptr != NULL)
- {
- if (mptr->mvn_idlist == NULL)
- {
- sidptr->site_id = mptr->mvn_addr.addr;
- strcpy(sidptr->id_string,mptr->mvn_name);
-
- temp = strlen(sidptr->id_string) + 1;
-
- cptr = &(sidptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- sidptr = (SiteId *) cptr;
- }
- else
- {
- /*
- copy the idlist that this maven client has been sending (see reflect.c)
- into the idlist we are presently building. mptr->mvn_idlist points to a
- struct IDMsgHdr, which we don't want, so skip over it.
- */
-
- count += mptr->mvn_idlist->nsids;
-
- cptr = (char *) mptr->mvn_idlist;
- cptr += sizeof(struct IDMsgHdr);
- temp = mptr->mvn_idlist_len - sizeof(struct IDMsgHdr);
-
- bcopy(cptr, (char *) sidptr, temp);
- cptr = (char *) sidptr;
- cptr += temp;
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- sidptr = (SiteId *) cptr;
- }
- mptr = mptr->mvn_nptr;
- }
-
- cltptr = chead;
- while (cltptr != NULL)
- {
- if (cltptr->clnt_config.flags & AUDIO_CAPABLE)
- {
- count++;
-
- sidptr->site_id = cltptr->clnt_addr.addr;
- strncpy(sidptr->id_string,cltptr->clnt_config.name,20);
-
- temp = strlen(sidptr->id_string) + 1;
- cptr = &(sidptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- sidptr = (SiteId *) cptr;
- }
- cltptr = cltptr->clnt_nptr;
- }
-
- count++;
-
- sidptr->site_id = myaddr.sin_addr.s_addr;
- strncpy(sidptr->id_string,"CU-Reflector ",20);
-
- temp = strlen("CU-Reflector") + 1;
- cptr = &(sidptr->id_string[temp]);
-
- while ((temp % 4) != 0)
- {
- temp++;
- cptr++;
- }
-
- idhptr = (struct IDMsgHdr *) &buffer[40];
- idhptr->flags = 0;
- idhptr->type = CTRL_TYPE_IDLIST;
- idhptr->confid = htons(vat_confid);
- idhptr->nsids = num_ucast + num_mcast + count;
- idhptr->ainfo = 0;
- idhptr->blksize = 0;
-
- msglen = cptr - &buffer[40];
- cptr = &buffer[40];
-
- mptr = mhead;
-
- while (mptr != NULL)
- {
- if (mptr->mvn_recv_type == UCAST)
- {
- tmp1.sin_family = AF_INET;
- tmp1.sin_addr.s_addr = htonl(mptr->mvn_addr.addr);
- tmp1.sin_port = htons(maven_port + 1);
-
- dolog("Sending Idlist of %d clients to UCAST maven %s \n",count, inet_ntoa(tmp1.sin_addr));
-
- if (sendto(maven_cntl_sock_out,cptr,msglen,0,&tmp1,sizeof(struct sockaddr_in)) != msglen)
- dolog("maven_cntl_sock_out sendto error");
- }
- mptr = mptr->mvn_nptr;
- }
- }
-
-
- void send_nv_ocp(nvcltptr)
- client *nvcltptr;
- {
-
- VideoPacketHeader *vidptr;
- client *ctmp;
- short audio = 0;
-
- unsigned char buffer[MAXMSG];
- unsigned char *msg = &buffer[40],*cptr;
-
- vidptr = (VideoPacketHeader *) msg;
-
- vidptr->conferenceid = conference_id;
-
- vidptr->routing.dest.family = htons(kReflector);
-
- bcopy(&myaddr.sin_addr.s_addr,&vidptr->routing.dest.addr,4);
-
- vidptr->routing.src.family = htons(kClient);
- vidptr->routing.src.port = htons(VID_PORT);
-
- bcopy(&nvcltptr->clnt_addr.addr,&vidptr->routing.src.addr,4);
-
- vidptr->seqNum = htonl(nvcltptr->clnt_seq + ++nvcltptr->clnt_ocp_cnt);
-
- /*
- dolog("send_nv_ocp seq # %D\n",vidptr->seqNum);
- */
-
- vidptr->message = htons(kOpenConnection);
- vidptr->dataType = htons(kConfigVideoType);
- vidptr->len = htons(HEADERLEN + OCDLEN);
-
- cptr = (unsigned char *) ((unsigned char *) vidptr + HEADERLEN);
-
- bcopy(&client_cnt,cptr,2);
- cptr += 2;
-
- bcopy(&nvcltptr->clnt_ocp_cnt,cptr,4);
- cptr += 4;
-
- *cptr++ = strlen(nvcltptr->clnt_config.name);
-
- strncpy(cptr,nvcltptr->clnt_config.name,19);
-
- cptr += 19;
-
- *cptr++ = 1;
- *cptr++ = 1;
-
- if (find_vat_client(nvcltptr->clnt_addr.addr) != NULL)
- {
- *cptr++ = REC_AUDIO | AUDIO_CAPABLE | WANT_LURCKERS;
- audio = 1;
- }
- else
- *cptr++ = 0;
-
- *cptr++ = NV_CLIENT_VERS;
-
- msg += HEADERLEN + OCDLEN;
-
- ctmp = chead;
- while (ctmp != NULL)
- {
- if (ctmp->clnt_flags & CLIENT)
- {
- bcopy(&ctmp->clnt_addr.addr,msg,4);
- msg += 4;
- if (audio)
- *msg++ = IWillRecAudio;
- else
- *msg++ = 0;
-
- *msg++ = 0;
- *msg++ = 1;
- *msg++ = 1;
- msg += 4;
- vidptr->len += 12;
- }
- ctmp = ctmp->clnt_nptr;
- }
-
- ctmp = chead;
- while (ctmp != NULL)
- {
- if ((ctmp->clnt_flags & (CLIENT | BCC_CLIENT)) && (ctmp->clnt_flags & HOLD_DOWN) == 0)
- {
- vidptr->routing.dest.addr = htonl(ctmp->clnt_addr.addr);
-
- if (sendto(vid_sock,(char *)vidptr,vidptr->len,0,&ctmp->clnt_addr,sizeof(struct sockaddr_in)) != vidptr->len)
- dolog("NV send to error in reflect\n");
- }
-
- ctmp = ctmp->clnt_nptr;
- }
-
- }
-
- vat_client *find_vat_client(caddr)
- unsigned long caddr;
- {
- vat_client *ctmp;
-
- ctmp = mhead;
-
- while (ctmp != NULL)
- {
- if (ctmp->mvn_addr.addr == caddr)
- return(ctmp);
- ctmp = ctmp->mvn_nptr;
- }
- return(NULL);
- }
-
- nv_wrt(srcptr,vidptr)
- client *srcptr;
- VideoPacketHeader *vidptr;
- {
- client *ctmp;
- unsigned char *cptr,*tmp;
- unsigned char id;
- unsigned short datatype,seqnum,message,client_id;
- unsigned long timestamp,ltmp;
- struct in_addr in;
- short len,wlen,err;
-
- cptr = ((unsigned char *) vidptr) + HEADERLEN;
-
- datatype = vidptr->dataType;
- bcopy(&datatype,cptr,sizeof(datatype));
-
- client_id = htons(srcptr->clnt_id);
-
- bcopy(&vidptr->seqNum,<mp,4);
- seqnum = ltmp; /* truncate to 16 bits for RTP header */
-
- message = ntohs(vidptr->message);
- len = ntohs(vidptr->len) - HEADERLEN + MHEADERLEN + SSRCLEN;
-
- timestamp = RTPTime();
- if (((timestamp - srcptr->clnt_sdesc_time) >> 16) >= NV_SDESC_TIMER)
- {
- srcptr->clnt_sdesc_time = timestamp;
-
- wlen = (strlen(srcptr->clnt_config.name) >> 2) + 3;
- cptr -= (wlen << 2);
-
- tmp = cptr;
- *tmp++ = SDESC | FINAL; /* RTP SDESC option is FINAL option */
- *tmp++ = wlen; /* option length */
- *((unsigned short *) tmp) = client_id; /* client id */
- tmp += sizeof(client_id);
- bcopy(&srcptr->clnt_addr.addr,tmp,sizeof(struct in_addr));
-
- /* client addr */
- tmp += sizeof(struct in_addr);
- strcpy(tmp,srcptr->clnt_config.name); /* client name */
-
- *(cptr - SSRCLEN) = SSRC; /* RTP SSRC option */
- }
- else
- {
- wlen = 0;
- *(cptr - SSRCLEN) = SSRC | FINAL; /* RTP SSRC option is FINAL option */
- }
-
- len += (wlen << 2);
-
- cptr -= MHEADERLEN + SSRCLEN;
- tmp = cptr;
-
- /* start of RTP header */
-
- /*
- *tmp++ = NVVERSION | client_id; /* nv version & channel id */
-
-
- *tmp++ = NVVERSION | NV_CHAN; /* nv version & channel id */
-
- *tmp = NVCONTENT | NVOBIT; /* nv content with RTP options */
-
- if (message == kFrameEndMessage)
- *tmp |= NVSBIT; /* nv framing bit */
-
- tmp++;
-
- *((unsigned short *) tmp) = seqnum; /* seq */
- tmp += sizeof(seqnum);
- timestamp = htonl(timestamp);
- bcopy(×tamp,tmp,sizeof(timestamp));
- tmp += sizeof(timestamp) + 1;
-
- /* RTP SSRC option */
- /* already set RTP option type */
-
- *tmp++ = SSRCLEN >> 2; /* RTP option length */
- *((unsigned short *) tmp) = client_id; /* client id */
- tmp += sizeof(client_id);
- bcopy(&srcptr->clnt_addr.addr,tmp,sizeof(struct in_addr)); /* client addr */
-
- if (send_to_nv(srcptr))
- {
- ctmp = chead;
- while (ctmp != NULL)
- {
- if (ctmp->clnt_flags & NV_UCLIENT)
- if (err = (sendto(nv_ucast_sock,cptr,len,0,&ctmp->clnt_addr,sizeof(struct sockaddr_in))) != len)
- dolog("nv ucast sendto error %d\n",err);
-
- ctmp = ctmp->clnt_nptr;
- }
- }
-
- if (nv_out_mcast_sock)
- if (err = (sendto(nv_out_mcast_sock,cptr,len,0,&nv_out_mcast,sizeof(struct sockaddr_in))) != len)
- dolog("nv mcast sendto error %d on nv_out_mcast_sock\n",err);
-
- if (nv_inout_mcast_sock)
- if (err = (sendto(nv_inout_mcast_sock,cptr,len,0,&nv_inout_mcast,sizeof(struct sockaddr_in))) != len)
- dolog("nv mcast sendto error %d\n on nv_inout_mcast_sock",err);
- }
-
- unsigned long RTPTime()
- {
- struct timeval t;
-
- gettimeofday(&t, NULL);
- return ((t.tv_sec + RTP_EPOCH_OFFSET) << 16) | ((t.tv_usec << 10) / 15625);
- }
-
- short send_to_nv(cltptr)
- client *cltptr;
- {
- short cnt;
-
- if (nv_client_cnt == 0)
- return(0);
-
- for (cnt=0; cnt<send_to_nv_cnt; cnt++)
- if (send_to_nv_list[cnt] == cltptr->clnt_addr.addr)
- {
- send_to_nv_timer[cnt] = 0;
- return(1);
- }
-
- if (send_to_nv_cnt < nv_streams)
- {
- send_to_nv_list[send_to_nv_cnt] = cltptr->clnt_addr.addr;
- send_to_nv_timer[cnt] = 0;
- send_to_nv_cnt++;
- return(1);
- }
- return(0);
- }
-